Дедупликация ресурсов в React Suspense: предотвращение дублирующих запросов | MLOG | MLOG

Теперь UserResource проверяет, существует ли ресурс в cache. Если да, возвращается кешированный ресурс. В противном случае инициируется новый запрос, и полученный Promise сохраняется в кеше. Это гарантирует, что для каждого уникального userId будет выполнен только один запрос.

2. Использование специализированной библиотеки кеширования (например, `lru-cache`)

Для более сложных сценариев кеширования рассмотрите возможность использования специализированной библиотеки кеширования, такой как lru-cache или аналогичной. Эти библиотеки предоставляют такие функции, как вытеснение из кеша на основе алгоритма наименее давно использовавшегося (LRU) или других политик, что может быть критически важно для управления использованием памяти, особенно при работе с большим количеством ресурсов.

Сначала установите библиотеку:

            
npm install lru-cache

            

Затем интегрируйте ее в ваш UserResource:

            
import React, { Suspense } from 'react';
import LRUCache from 'lru-cache';

const fetchUser = (userId) => {
  console.log(`Fetching user with ID: ${userId}`); // Simulate network request
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: userId, name: `User ${userId}`, email: `user${userId}@example.com` });
    }, 1000); // Simulate network latency
  });
};

const cache = new LRUCache({
  max: 100, // Maximum number of items in the cache
  ttl: 60000, // Time-to-live in milliseconds (1 minute)
});

const UserResource = (userId) => {
  if (!cache.has(userId)) {
    let promise = null;
    let status = 'pending'; // pending, success, error
    let result;

    const suspender = fetchUser(userId).then(
      (r) => {
        status = 'success';
        result = r;
        cache.set(userId, {
          read() {
            return result;
          },
        });
      },
      (e) => {
        status = 'error';
        result = e;
        cache.set(userId, {
          read() {
            throw result;
          },
        });
      }
    );

    cache.set(userId, {
        read() {
            if (status === 'pending') {
                throw suspender;
            } else if (status === 'error') {
                throw result;
            }
            return result;
        }
    });
  }

  return cache.get(userId);
};


const UserProfile = ({ userId }) => {
  const user = UserResource(userId).read();
  return (
    

User Profile

ID: {user.id}

Name: {user.name}

Email: {user.email}

); }; const UserDetails = ({ userId }) => { const user = UserResource(userId).read(); return (

User Details

ID: {user.id}

Name: {user.name}

); }; const App = () => { return ( Loading...
}> ); }; export default App;

Этот подход обеспечивает больший контроль над размером кеша и политикой истечения срока действия.

3. Объединение запросов с помощью библиотек, таких как `axios-extensions`

Библиотеки, такие как axios-extensions, предлагают более продвинутые функции, например, объединение запросов (request coalescing). Объединение запросов комбинирует несколько идентичных запросов в один, что дополнительно оптимизирует использование сети. Это особенно полезно в сценариях, когда запросы инициируются очень близко друг к другу по времени.

Сначала установите библиотеку:

            
npm install axios axios-extensions

            

Затем настройте Axios с адаптером cache, предоставляемым axios-extensions.

Пример использования `axios-extensions` и создания ресурса:

            
import React, { Suspense } from 'react';
import axios from 'axios';
import { cacheAdapterEnhancer, throttleAdapterEnhancer } from 'axios-extensions';

const instance = axios.create({
  baseURL: 'https://api.example.com', // Replace with your API endpoint
  adapter: cacheAdapterEnhancer(axios.defaults.adapter, { enabledByDefault: true }),
});

const fetchUser = async (userId) => {
  console.log(`Fetching user with ID: ${userId}`); // Simulate network request
  const response = await instance.get(`/users/${userId}`);
  return response.data;
};


const UserResource = (userId) => {
    let promise = null;
    let status = 'pending'; // pending, success, error
    let result;

    const suspender = fetchUser(userId).then(
        (r) => {
            status = 'success';
            result = r;
        },
        (e) => {
            status = 'error';
            result = e;
        }
    );

    return {
        read() {
            if (status === 'pending') {
                throw suspender;
            } else if (status === 'error') {
                throw result;
            }
            return result;
        },
    };
};


const UserProfile = ({ userId }) => {
  const user = UserResource(userId).read();
  return (
    

User Profile

ID: {user.id}

Name: {user.name}

Email: {user.email}

); }; const UserDetails = ({ userId }) => { const user = UserResource(userId).read(); return (

User Details

ID: {user.id}

Name: {user.name}

); }; const App = () => { return ( Loading...
}> ); }; export default App;

Это настраивает Axios на использование адаптера кеша, автоматически кеширующего ответы на основе конфигурации запроса. Функция cacheAdapterEnhancer предоставляет опции для настройки кеша, такие как установка максимального размера кеша или времени истечения срока действия. throttleAdapterEnhancer также можно использовать для ограничения количества запросов к серверу в течение определенного периода времени, что дополнительно оптимизирует производительность.

Лучшие практики дедупликации ресурсов

Глобальные аспекты получения и дедупликации данных

При разработке стратегий получения данных для глобальной аудитории необходимо учитывать несколько факторов:

Например, веб-сайт для бронирования путешествий, ориентированный на глобальную аудиторию, может использовать CDN для предоставления данных о наличии авиабилетов и отелей с серверов, расположенных в разных регионах. Веб-сайт также будет использовать API для конвертации валют, чтобы отображать цены в местной валюте пользователя, и предоставлять опции для фильтрации результатов поиска на основе языковых предпочтений.

Заключение

Дедупликация ресурсов — это важная техника оптимизации для приложений React, использующих Suspense. Предотвращая дублирующие запросы на получение данных, вы можете значительно улучшить производительность, снизить нагрузку на сервер и улучшить пользовательский опыт. Независимо от того, выберете ли вы реализацию простого кеша Promise или воспользуетесь более продвинутыми библиотеками, такими как lru-cache или axios-extensions, главное — понимать основные принципы и выбирать решение, которое наилучшим образом соответствует вашим конкретным потребностям. Не забывайте учитывать глобальные факторы, такие как CDN, локализация и доступность, при разработке стратегий получения данных для разнообразной аудитории. Внедряя эти лучшие практики, вы сможете создавать более быстрые, эффективные и удобные для пользователя приложения React.